st_layers(here("prac3_data", "gadm36_AUS.gpkg"))
Driver: GPKG 
Available layers:
Ausoutline <- st_read(here("prac3_data", "gadm36_AUS.gpkg"), 
                      layer='gadm36_AUS_0')
Reading layer `gadm36_AUS_0' from data source `D:\CASA\GIS\prac3_data\gadm36_AUS.gpkg' using driver `GPKG'
Simple feature collection with 1 feature and 2 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 112.9211 ymin: -55.11694 xmax: 159.1092 ymax: -9.142176
Geodetic CRS:  WGS 84
# re-project or transform CRS
AusoutlinePROJECTED <- Ausoutline %>%
  st_transform(.,3112) # GDA94, a local CRS for Australia

print(AusoutlinePROJECTED)
Simple feature collection with 1 feature and 2 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -2083066 ymin: -6460625 xmax: 2346599 ymax: -1115948
Projected CRS: GDA94 / Geoscience Australia Lambert
  GID_0    NAME_0                           geom
1   AUS Australia MULTIPOLYGON (((1775780 -64...
##From sf to sp
#AusoutlineSP <- Ausoutline %>%
#  as(., "Spatial")

##From sp to sf
#AusoutlineSF <- AusoutlineSP %>%
#  st_as_sf()
library(raster)
library(terra)
jan<-terra::rast(here("prac3_data", "wc2.1_5m_tavg_01.tif"))
# have a look at the raster layer jan
jan
class       : SpatRaster 
dimensions  : 2160, 4320, 1  (nrow, ncol, nlyr)
resolution  : 0.08333333, 0.08333333  (x, y)
extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326) 
source      : wc2.1_5m_tavg_01.tif 
name        : wc2.1_5m_tavg_01 
min value   :          -46.042 
max value   :           34.065 
plot(jan)

using the Mollweide projection saved to a new object. The Mollweide projection retains area proportions whilst compromising accuracy of angle and shape

# set the proj 4 to a new object

pr1 <- terra::project(jan, "+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs")

#or....

newproj<-"ESRI:54009"
# get the jan raster and give it the new proj4
pr1 <- jan %>%
  terra::project(., newproj)
plot(pr1)

#back to WGS 84
pr1 <- pr1 %>%
  terra::project(., "EPSG:4326")
plot(pr1)

# look in our folder, find the files that end with .tif and 
library(fs)
dir_info("D:/CASA/GIS/prac3_data/") 
# select the data we actually want
library(tidyverse)
listfiles<-dir_info("D:/CASA/GIS/prac3_data/") %>%
  filter(str_detect(path, ".tif")) %>%
  dplyr::select(path)%>%
  pull()

#have a look at the file names 
listfiles
D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_01.tif D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_02.tif 
D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_03.tif D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_04.tif 
D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_05.tif D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_06.tif 
D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_07.tif D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_08.tif 
D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_09.tif D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_10.tif 
D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_11.tif D:/CASA/GIS/prac3_data/wc2.1_5m_tavg_12.tif 

Then load all of the data straight into a SpatRaster. A SpatRaster is a collection of raster layers with the same spatial extent and resolution.

worldclimtemp <- listfiles %>%
  terra::rast()
  
#have a look at the raster stack
worldclimtemp
class       : SpatRaster 
dimensions  : 2160, 4320, 12  (nrow, ncol, nlyr)
resolution  : 0.08333333, 0.08333333  (x, y)
extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326) 
sources     : wc2.1_5m_tavg_01.tif  
              wc2.1_5m_tavg_02.tif  
              wc2.1_5m_tavg_03.tif  
              ... and 9 more source(s)
names       : wc2.1~vg_01, wc2.1~vg_02, wc2.1~vg_03, wc2.1~vg_04, wc2.1~vg_05, wc2.1~vg_06, ... 
min values  :     -46.042,     -44.800,     -57.986,     -64.200,     -64.829,     -64.395, ... 
max values  :      34.065,      32.908,      33.081,      34.277,      36.299,      38.458, ... 
# access the january layer
worldclimtemp[[1]]
class       : SpatRaster 
dimensions  : 2160, 4320, 1  (nrow, ncol, nlyr)
resolution  : 0.08333333, 0.08333333  (x, y)
extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326) 
source      : wc2.1_5m_tavg_01.tif 
name        : wc2.1_5m_tavg_01 
min value   :          -46.042 
max value   :           34.065 
#rename the layers
month <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", 
           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

names(worldclimtemp) <- month
# get data for January using new layer name
worldclimtemp$Jan
class       : SpatRaster 
dimensions  : 2160, 4320, 1  (nrow, ncol, nlyr)
resolution  : 0.08333333, 0.08333333  (x, y)
extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326) 
source      : wc2.1_5m_tavg_01.tif 
name        :     Jan 
min value   : -46.042 
max value   :  34.065 

Using a raster stack we can extract data with a single command!! For example, make a dataframe of some sample sites — Australian cities/towns.

site <- c("Brisbane", "Melbourne", "Perth", "Sydney", "Broome", "Darwin", "Orange", 
          "Bunbury", "Cairns", "Adelaide", "Gold Coast", "Canberra", "Newcastle", 
          "Wollongong", "Logan City" )
lon <- c(153.03, 144.96, 115.86, 151.21, 122.23, 130.84, 149.10, 115.64, 145.77, 
         138.6, 153.43, 149.13, 151.78, 150.89, 153.12)
lat <- c(-27.47, -37.91, -31.95, -33.87, 17.96, -12.46, -33.28, -33.33, -16.92, 
         -34.93, -28, -35.28, -32.93, -34.42, -27.64)
#Put all of this inforamtion into one list 
samples <- data.frame(site, lon, lat, row.names="site")
# Extract the data from the Rasterstack for all points 
AUcitytemp<- terra::extract(worldclimtemp, samples)

Add the city names to the rows of AUcitytemp

Aucitytemp2 <- AUcitytemp %>% 
  as_tibble()%>% 
  add_column(Site = site, .before = "Jan")

take Perth as an example. We can subset our data either using the row name:

Perthtemp <- Aucitytemp2 %>%
  filter(site=="Perth")

Make a histogram of Perth’s temperature. The tibble stored the data as double and the base hist() function needs it as numeric..

hist(as.numeric(Perthtemp))
Warning: NAs introduced by coercion

library(tidyverse)
#define where you want the breaks in the historgram
userbreak<-c(8,10,12,14,16,18,20,22,24,26)

# remove the ID and site columns
Perthtemp <- Aucitytemp2 %>%
  filter(site=="Perth")

t<-Perthtemp %>%
 dplyr::select(Jan:Dec)

  hist((as.numeric(t)), 
     breaks=userbreak, 
     col="red", 
     main="Histogram of Perth Temperature", 
     xlab="Temperature", 
     ylab="Frequency")

#Check out the histogram information R generated
histinfo <- as.numeric(t) %>%
  as.numeric()%>%
  hist(.)


histinfo
$breaks
[1] 12 14 16 18 20 22 24 26

$counts
[1] 2 2 2 1 1 2 2

$density
[1] 0.08333333 0.08333333 0.08333333 0.04166667 0.04166667 0.08333333 0.08333333

$mids
[1] 13 15 17 19 21 23 25

$xname
[1] "."

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

breaks — the cut off points for the bins (or bars), we just specified these counts — the number of cells in each bin midpoints — the middle value for each bin density — the density of data per bin

Check the layer by plotting the geometr

plot(Ausoutline$geom)

#simplify the .shp with lots of points
AusoutSIMPLE <- Ausoutline %>%
  st_simplify(., dTolerance = 1000) %>% #controls the level of generalisation in the units of the map
  st_geometry()%>%
  plot()

make sure that both of our layers are in the same coordinate reference system before combine

print(Ausoutline)
Simple feature collection with 1 feature and 2 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 112.9211 ymin: -55.11694 xmax: 159.1092 ymax: -9.142176
Geodetic CRS:  WGS 84
  GID_0    NAME_0                           geom
1   AUS Australia MULTIPOLYGON (((158.6928 -5...
#this works nicely for rasters
crs(worldclimtemp)
[1] "GEOGCRS[\"WGS 84\",\n    DATUM[\"World Geodetic System 1984\",\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    ID[\"EPSG\",4326]]"
Austemp <- Ausoutline %>%
  # now crop our temp data to the extent
  terra::crop(worldclimtemp,.)

# plot the output
plot(Austemp)

exactAus<-terra::mask(Austemp, Ausoutline)
exactAus
class       : SpatRaster 
dimensions  : 551, 554, 12  (nrow, ncol, nlyr)
resolution  : 0.08333333, 0.08333333  (x, y)
extent      : 112.9167, 159.0833, -55.08333, -9.166667  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326) 
source      : memory 
names       :     Jan,      Feb,       Mar,       Apr,    May,    Jun, ... 
min values  :  6.4875,  6.53125,  5.845714,  4.571428,  2.642, -0.394, ... 
max values  : 34.0650, 32.90800, 31.986000, 30.400000, 28.800, 27.200, ... 
#subset using the known location of the raster
hist(exactAus[[3]], col="red", main ="March temperature")

#make our raster into a data.frame to be compatible with ggplot2, using a dataframe or tibble
exactAusdf <- exactAus %>%
  as.data.frame()
library(ggplot2)
# set up the basic histogram
gghist <- ggplot(exactAusdf, 
                 aes(x=Mar)) + 
  geom_histogram(color="black", 
                 fill="white")+
  labs(title="Ggplot2 histogram of Australian March temperatures", 
       x="Temperature", 
       y="Frequency")
# add a vertical line to the hisogram showing mean tempearture
gghist + geom_vline(aes(xintercept=mean(Mar, 
                                        na.rm=TRUE)),
            color="blue", 
            linetype="dashed", 
            size=1)+
  theme(plot.title = element_text(hjust = 0.5))

put our variable (months) into a one column using pivot_longer()

squishdata<-exactAusdf%>%
  pivot_longer(
  cols = 1:12,
  names_to = "Month",
  values_to = "Temp"
)

select two month

twomonths <- squishdata %>%
  # | = OR
  filter(., Month=="Jan" | Month=="Jun")
meantwomonths <- twomonths %>%
  group_by(Month) %>%
  summarise(mean=mean(Temp, na.rm=TRUE))

meantwomonths
ggplot(twomonths, aes(x=Temp, color=Month, fill=Month)) +
  geom_histogram(position="identity", alpha=0.5)+
  geom_vline(data=meantwomonths, 
             aes(xintercept=mean, 
                 color=Month),
             linetype="dashed")+
  labs(title="Ggplot2 histogram of Australian Jan and Jun
       temperatures",
       x="Temperature",
       y="Frequency")+
  theme_classic()+
  theme(plot.title = element_text(hjust = 0.5))

data_complete_cases <- squishdata %>%
  drop_na()%>% #dropped all the NAs
  # Month column map in descending order (e.g. Jan, Feb, March..)
  mutate(Month = factor(Month, levels = c("Jan","Feb","Mar",
                                          "Apr","May","Jun",
                                          "Jul","Aug","Sep",
                                          "Oct","Nov","Dec")))

# Plot faceted histogram
ggplot(data_complete_cases, aes(x=Temp, na.rm=TRUE))+
  geom_histogram(color="black", binwidth = 5)+
  labs(title="Ggplot2 faceted histogram of Australian temperatures", 
       x="Temperature",
       y="Frequency")+
  facet_grid(Month ~ .)+
  theme(plot.title = element_text(hjust = 0.5))

# mean per month
meanofall <- squishdata %>%
  group_by(Month) %>%
  summarise(mean = mean(Temp, na.rm=TRUE))

# print the top 1
head(meanofall, n=1)
# standard deviation per month
sdofall <- squishdata %>%
  group_by(Month) %>%
  summarize(sd = sd(Temp, na.rm=TRUE))

# maximum per month
maxofall <- squishdata %>%
  group_by(Month) %>%
  summarize(max = max(Temp, na.rm=TRUE))

# minimum per month
minofall <- squishdata %>%
  group_by(Month) %>%
  summarize(min = min(Temp, na.rm=TRUE))

# Interquartlie range per month
IQRofall <- squishdata %>%
  group_by(Month) %>%
  summarize(IQR = IQR(Temp, na.rm=TRUE))

# perhaps you want to store multiple outputs in one list..
lotsofstats <- squishdata %>%
  group_by(Month) %>%
  summarize(IQR = IQR(Temp, na.rm=TRUE), 
            max=max(Temp, na.rm=T))

# or you want to know the mean (or some other stat) 
#for the whole year as opposed to each month...

meanwholeyear=squishdata %>%
  summarize(meanyear = mean(Temp, na.rm=TRUE))

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIlByYWN0aWNhbCAzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3J9DQojcmVhZCB0aGUgcGFja2FnZSBhbmQgbGF5ZXINCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGhlcmUpDQpzdF9sYXllcnMoaGVyZSgicHJhYzNfZGF0YSIsICJnYWRtMzZfQVVTLmdwa2ciKSkNCg0KQXVzb3V0bGluZSA8LSBzdF9yZWFkKGhlcmUoInByYWMzX2RhdGEiLCAiZ2FkbTM2X0FVUy5ncGtnIiksIA0KICAgICAgICAgICAgICAgICAgICAgIGxheWVyPSdnYWRtMzZfQVVTXzAnKQ0KDQpwcmludChBdXNvdXRsaW5lKQ0Kc3RfY3JzKEF1c291dGxpbmUpJHByb2o0c3RyaW5nDQoNCiMjc2V0IHNwYXRpYWwgcmVmZXJlbmNlIHN5c3RlbSwgb25seSB1c2VmdWwgaWYgdGhlcmUgaXMgbm8gQ1JTDQojQXVzb3V0bGluZSA8LSBzdF9yZWFkKGhlcmUoInByYWMzX2RhdGEiLCAiZ2FkbTM2X0FVUy5ncGtnIiksIA0KIyAgICAgICAgICAgICAgICAgICAgICBsYXllcj0nZ2FkbTM2X0FVU18wJykgJT4lIA0KIyAgc3Rfc2V0X2Nycyg0MzI2KQ0KYGBgDQoNCmBgYHtyfQ0KIyByZS1wcm9qZWN0IG9yIHRyYW5zZm9ybSBDUlMNCkF1c291dGxpbmVQUk9KRUNURUQgPC0gQXVzb3V0bGluZSAlPiUNCiAgc3RfdHJhbnNmb3JtKC4sMzExMikgIyBHREE5NCwgYSBsb2NhbCBDUlMgZm9yIEF1c3RyYWxpYQ0KDQpwcmludChBdXNvdXRsaW5lUFJPSkVDVEVEKQ0KYGBgDQoNCmBgYHtyfQ0KIyNGcm9tIHNmIHRvIHNwDQojQXVzb3V0bGluZVNQIDwtIEF1c291dGxpbmUgJT4lDQojICBhcyguLCAiU3BhdGlhbCIpDQoNCiMjRnJvbSBzcCB0byBzZg0KI0F1c291dGxpbmVTRiA8LSBBdXNvdXRsaW5lU1AgJT4lDQojICBzdF9hc19zZigpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHJhc3RlcikNCmxpYnJhcnkodGVycmEpDQpqYW48LXRlcnJhOjpyYXN0KGhlcmUoInByYWMzX2RhdGEiLCAid2MyLjFfNW1fdGF2Z18wMS50aWYiKSkNCiMgaGF2ZSBhIGxvb2sgYXQgdGhlIHJhc3RlciBsYXllciBqYW4NCmphbg0KYGBgDQoNCmBgYHtyfQ0KcGxvdChqYW4pDQpgYGANCg0KdXNpbmcgdGhlIE1vbGx3ZWlkZSBwcm9qZWN0aW9uIHNhdmVkIHRvIGEgbmV3IG9iamVjdC4gVGhlIE1vbGx3ZWlkZSBwcm9qZWN0aW9uIHJldGFpbnMgYXJlYSBwcm9wb3J0aW9ucyB3aGlsc3QgY29tcHJvbWlzaW5nIGFjY3VyYWN5IG9mIGFuZ2xlIGFuZCBzaGFwZQ0KYGBge3J9DQojIHNldCB0aGUgcHJvaiA0IHRvIGEgbmV3IG9iamVjdA0KDQpwcjEgPC0gdGVycmE6OnByb2plY3QoamFuLCAiK3Byb2o9bW9sbCArbG9uXzA9MCAreF8wPTAgK3lfMD0wICtlbGxwcz1XR1M4NCArZGF0dW09V0dTODQgK3VuaXRzPW0gK25vX2RlZnMiKQ0KDQojb3IuLi4uDQoNCm5ld3Byb2o8LSJFU1JJOjU0MDA5Ig0KIyBnZXQgdGhlIGphbiByYXN0ZXIgYW5kIGdpdmUgaXQgdGhlIG5ldyBwcm9qNA0KcHIxIDwtIGphbiAlPiUNCiAgdGVycmE6OnByb2plY3QoLiwgbmV3cHJvaikNCnBsb3QocHIxKQ0KYGBgDQpgYGB7cn0NCiNiYWNrIHRvIFdHUyA4NA0KcHIxIDwtIHByMSAlPiUNCiAgdGVycmE6OnByb2plY3QoLiwgIkVQU0c6NDMyNiIpDQpwbG90KHByMSkNCmBgYA0KDQpgYGB7cn0NCiMgbG9vayBpbiBvdXIgZm9sZGVyLCBmaW5kIHRoZSBmaWxlcyB0aGF0IGVuZCB3aXRoIC50aWYgYW5kIA0KbGlicmFyeShmcykNCmRpcl9pbmZvKCJEOi9DQVNBL0dJUy9wcmFjM19kYXRhLyIpIA0KYGBgDQoNCmBgYHtyfQ0KIyBzZWxlY3QgdGhlIGRhdGEgd2UgYWN0dWFsbHkgd2FudA0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaXN0ZmlsZXM8LWRpcl9pbmZvKCJEOi9DQVNBL0dJUy9wcmFjM19kYXRhLyIpICU+JQ0KICBmaWx0ZXIoc3RyX2RldGVjdChwYXRoLCAiLnRpZiIpKSAlPiUNCiAgZHBseXI6OnNlbGVjdChwYXRoKSU+JQ0KICBwdWxsKCkNCg0KI2hhdmUgYSBsb29rIGF0IHRoZSBmaWxlIG5hbWVzIA0KbGlzdGZpbGVzDQpgYGANCg0KVGhlbiBsb2FkIGFsbCBvZiB0aGUgZGF0YSBzdHJhaWdodCBpbnRvIGEgU3BhdFJhc3Rlci4gQSBTcGF0UmFzdGVyIGlzIGEgY29sbGVjdGlvbiBvZiByYXN0ZXIgbGF5ZXJzIHdpdGggdGhlIHNhbWUgc3BhdGlhbCBleHRlbnQgYW5kIHJlc29sdXRpb24uDQpgYGB7cn0NCndvcmxkY2xpbXRlbXAgPC0gbGlzdGZpbGVzICU+JQ0KICB0ZXJyYTo6cmFzdCgpDQogIA0KI2hhdmUgYSBsb29rIGF0IHRoZSByYXN0ZXIgc3RhY2sNCndvcmxkY2xpbXRlbXANCmBgYA0KDQpgYGB7cn0NCiMgYWNjZXNzIHRoZSBqYW51YXJ5IGxheWVyDQp3b3JsZGNsaW10ZW1wW1sxXV0NCmBgYA0KYGBge3J9DQojcmVuYW1lIHRoZSBsYXllcnMNCm1vbnRoIDwtIGMoIkphbiIsICJGZWIiLCAiTWFyIiwgIkFwciIsICJNYXkiLCAiSnVuIiwgDQogICAgICAgICAgICJKdWwiLCAiQXVnIiwgIlNlcCIsICJPY3QiLCAiTm92IiwgIkRlYyIpDQoNCm5hbWVzKHdvcmxkY2xpbXRlbXApIDwtIG1vbnRoDQpgYGANCg0KYGBge3J9DQojIGdldCBkYXRhIGZvciBKYW51YXJ5IHVzaW5nIG5ldyBsYXllciBuYW1lDQp3b3JsZGNsaW10ZW1wJEphbg0KYGBgDQoNClVzaW5nIGEgcmFzdGVyIHN0YWNrIHdlIGNhbiBleHRyYWN0IGRhdGEgd2l0aCBhIHNpbmdsZSBjb21tYW5kISEgDQpGb3IgZXhhbXBsZSwgbWFrZSBhIGRhdGFmcmFtZSBvZiBzb21lIHNhbXBsZSBzaXRlcyDigJQgQXVzdHJhbGlhbiBjaXRpZXMvdG93bnMuDQpgYGB7cn0NCnNpdGUgPC0gYygiQnJpc2JhbmUiLCAiTWVsYm91cm5lIiwgIlBlcnRoIiwgIlN5ZG5leSIsICJCcm9vbWUiLCAiRGFyd2luIiwgIk9yYW5nZSIsIA0KICAgICAgICAgICJCdW5idXJ5IiwgIkNhaXJucyIsICJBZGVsYWlkZSIsICJHb2xkIENvYXN0IiwgIkNhbmJlcnJhIiwgIk5ld2Nhc3RsZSIsIA0KICAgICAgICAgICJXb2xsb25nb25nIiwgIkxvZ2FuIENpdHkiICkNCmxvbiA8LSBjKDE1My4wMywgMTQ0Ljk2LCAxMTUuODYsIDE1MS4yMSwgMTIyLjIzLCAxMzAuODQsIDE0OS4xMCwgMTE1LjY0LCAxNDUuNzcsIA0KICAgICAgICAgMTM4LjYsIDE1My40MywgMTQ5LjEzLCAxNTEuNzgsIDE1MC44OSwgMTUzLjEyKQ0KbGF0IDwtIGMoLTI3LjQ3LCAtMzcuOTEsIC0zMS45NSwgLTMzLjg3LCAxNy45NiwgLTEyLjQ2LCAtMzMuMjgsIC0zMy4zMywgLTE2LjkyLCANCiAgICAgICAgIC0zNC45MywgLTI4LCAtMzUuMjgsIC0zMi45MywgLTM0LjQyLCAtMjcuNjQpDQojUHV0IGFsbCBvZiB0aGlzIGluZm9yYW10aW9uIGludG8gb25lIGxpc3QgDQpzYW1wbGVzIDwtIGRhdGEuZnJhbWUoc2l0ZSwgbG9uLCBsYXQsIHJvdy5uYW1lcz0ic2l0ZSIpDQojIEV4dHJhY3QgdGhlIGRhdGEgZnJvbSB0aGUgUmFzdGVyc3RhY2sgZm9yIGFsbCBwb2ludHMgDQpBVWNpdHl0ZW1wPC0gdGVycmE6OmV4dHJhY3Qod29ybGRjbGltdGVtcCwgc2FtcGxlcykNCmBgYA0KDQpBZGQgdGhlIGNpdHkgbmFtZXMgdG8gdGhlIHJvd3Mgb2YgQVVjaXR5dGVtcA0KYGBge3J9DQpBdWNpdHl0ZW1wMiA8LSBBVWNpdHl0ZW1wICU+JSANCiAgYXNfdGliYmxlKCklPiUgDQogIGFkZF9jb2x1bW4oU2l0ZSA9IHNpdGUsIC5iZWZvcmUgPSAiSmFuIikNCmBgYA0KDQp0YWtlIFBlcnRoIGFzIGFuIGV4YW1wbGUuIFdlIGNhbiBzdWJzZXQgb3VyIGRhdGEgZWl0aGVyIHVzaW5nIHRoZSByb3cgbmFtZToNCmBgYHtyfQ0KUGVydGh0ZW1wIDwtIEF1Y2l0eXRlbXAyICU+JQ0KICBmaWx0ZXIoc2l0ZT09IlBlcnRoIikNCmBgYA0KDQpNYWtlIGEgaGlzdG9ncmFtIG9mIFBlcnRo4oCZcyB0ZW1wZXJhdHVyZS4gVGhlIHRpYmJsZSBzdG9yZWQgdGhlIGRhdGEgYXMgZG91YmxlIGFuZCB0aGUgYmFzZSBoaXN0KCkgZnVuY3Rpb24gbmVlZHMgaXQgYXMgbnVtZXJpYy4uDQpgYGB7cn0NCmhpc3QoYXMubnVtZXJpYyhQZXJ0aHRlbXApKQ0KYGBgDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KI2RlZmluZSB3aGVyZSB5b3Ugd2FudCB0aGUgYnJlYWtzIGluIHRoZSBoaXN0b3JncmFtDQp1c2VyYnJlYWs8LWMoOCwxMCwxMiwxNCwxNiwxOCwyMCwyMiwyNCwyNikNCg0KIyByZW1vdmUgdGhlIElEIGFuZCBzaXRlIGNvbHVtbnMNClBlcnRodGVtcCA8LSBBdWNpdHl0ZW1wMiAlPiUNCiAgZmlsdGVyKHNpdGU9PSJQZXJ0aCIpDQoNCnQ8LVBlcnRodGVtcCAlPiUNCiBkcGx5cjo6c2VsZWN0KEphbjpEZWMpDQoNCiAgaGlzdCgoYXMubnVtZXJpYyh0KSksIA0KICAgICBicmVha3M9dXNlcmJyZWFrLCANCiAgICAgY29sPSJyZWQiLCANCiAgICAgbWFpbj0iSGlzdG9ncmFtIG9mIFBlcnRoIFRlbXBlcmF0dXJlIiwgDQogICAgIHhsYWI9IlRlbXBlcmF0dXJlIiwgDQogICAgIHlsYWI9IkZyZXF1ZW5jeSIpDQpgYGANCmBgYHtyfQ0KI0NoZWNrIG91dCB0aGUgaGlzdG9ncmFtIGluZm9ybWF0aW9uIFIgZ2VuZXJhdGVkDQpoaXN0aW5mbyA8LSBhcy5udW1lcmljKHQpICU+JQ0KICBhcy5udW1lcmljKCklPiUNCiAgaGlzdCguKQ0KDQpoaXN0aW5mbw0KYGBgDQpicmVha3Mg4oCUIHRoZSBjdXQgb2ZmIHBvaW50cyBmb3IgdGhlIGJpbnMgKG9yIGJhcnMpLCB3ZSBqdXN0IHNwZWNpZmllZCB0aGVzZQ0KY291bnRzIOKAlCB0aGUgbnVtYmVyIG9mIGNlbGxzIGluIGVhY2ggYmluDQptaWRwb2ludHMg4oCUIHRoZSBtaWRkbGUgdmFsdWUgZm9yIGVhY2ggYmluDQpkZW5zaXR5IOKAlCB0aGUgZGVuc2l0eSBvZiBkYXRhIHBlciBiaW4NCg0KQ2hlY2sgdGhlIGxheWVyIGJ5IHBsb3R0aW5nIHRoZSBnZW9tZXRyDQpgYGB7cn0NCnBsb3QoQXVzb3V0bGluZSRnZW9tKQ0KYGBgDQpgYGB7cn0NCiNzaW1wbGlmeSB0aGUgLnNocCB3aXRoIGxvdHMgb2YgcG9pbnRzDQpBdXNvdXRTSU1QTEUgPC0gQXVzb3V0bGluZSAlPiUNCiAgc3Rfc2ltcGxpZnkoLiwgZFRvbGVyYW5jZSA9IDEwMDApICU+JSAjY29udHJvbHMgdGhlIGxldmVsIG9mIGdlbmVyYWxpc2F0aW9uIGluIHRoZSB1bml0cyBvZiB0aGUgbWFwDQogIHN0X2dlb21ldHJ5KCklPiUNCiAgcGxvdCgpDQpgYGANCg0KbWFrZSBzdXJlIHRoYXQgYm90aCBvZiBvdXIgbGF5ZXJzIGFyZSBpbiB0aGUgc2FtZSBjb29yZGluYXRlIHJlZmVyZW5jZSBzeXN0ZW0gYmVmb3JlIGNvbWJpbmUNCmBgYHtyfQ0KcHJpbnQoQXVzb3V0bGluZSkNCg0KI3RoaXMgd29ya3MgbmljZWx5IGZvciByYXN0ZXJzDQpjcnMod29ybGRjbGltdGVtcCkNCmBgYA0KDQpgYGB7cn0NCkF1c3RlbXAgPC0gQXVzb3V0bGluZSAlPiUNCiAgIyBub3cgY3JvcCBvdXIgdGVtcCBkYXRhIHRvIHRoZSBleHRlbnQNCiAgdGVycmE6OmNyb3Aod29ybGRjbGltdGVtcCwuKQ0KDQojIHBsb3QgdGhlIG91dHB1dA0KcGxvdChBdXN0ZW1wKQ0KYGBgDQpgYGB7cn0NCmV4YWN0QXVzPC10ZXJyYTo6bWFzayhBdXN0ZW1wLCBBdXNvdXRsaW5lKQ0KZXhhY3RBdXMNCmBgYA0KYGBge3J9DQojc3Vic2V0IHVzaW5nIHRoZSBrbm93biBsb2NhdGlvbiBvZiB0aGUgcmFzdGVyDQpoaXN0KGV4YWN0QXVzW1szXV0sIGNvbD0icmVkIiwgbWFpbiA9Ik1hcmNoIHRlbXBlcmF0dXJlIikNCmBgYA0KYGBge3J9DQojbWFrZSBvdXIgcmFzdGVyIGludG8gYSBkYXRhLmZyYW1lIHRvIGJlIGNvbXBhdGlibGUgd2l0aCBnZ3Bsb3QyLCB1c2luZyBhIGRhdGFmcmFtZSBvciB0aWJibGUNCmV4YWN0QXVzZGYgPC0gZXhhY3RBdXMgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KIyBzZXQgdXAgdGhlIGJhc2ljIGhpc3RvZ3JhbQ0KZ2doaXN0IDwtIGdncGxvdChleGFjdEF1c2RmLCANCiAgICAgICAgICAgICAgICAgYWVzKHg9TWFyKSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0oY29sb3I9ImJsYWNrIiwgDQogICAgICAgICAgICAgICAgIGZpbGw9IndoaXRlIikrDQogIGxhYnModGl0bGU9IkdncGxvdDIgaGlzdG9ncmFtIG9mIEF1c3RyYWxpYW4gTWFyY2ggdGVtcGVyYXR1cmVzIiwgDQogICAgICAgeD0iVGVtcGVyYXR1cmUiLCANCiAgICAgICB5PSJGcmVxdWVuY3kiKQ0KIyBhZGQgYSB2ZXJ0aWNhbCBsaW5lIHRvIHRoZSBoaXNvZ3JhbSBzaG93aW5nIG1lYW4gdGVtcGVhcnR1cmUNCmdnaGlzdCArIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVhbihNYXIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIGNvbG9yPSJibHVlIiwgDQogICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgDQogICAgICAgICAgICBzaXplPTEpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCmBgYA0KcHV0IG91ciB2YXJpYWJsZSAobW9udGhzKSBpbnRvIGEgb25lIGNvbHVtbiB1c2luZyBwaXZvdF9sb25nZXIoKQ0KYGBge3J9DQpzcXVpc2hkYXRhPC1leGFjdEF1c2RmJT4lDQogIHBpdm90X2xvbmdlcigNCiAgY29scyA9IDE6MTIsDQogIG5hbWVzX3RvID0gIk1vbnRoIiwNCiAgdmFsdWVzX3RvID0gIlRlbXAiDQopDQpgYGANCg0Kc2VsZWN0IHR3byBtb250aA0KYGBge3J9DQp0d29tb250aHMgPC0gc3F1aXNoZGF0YSAlPiUNCiAgIyB8ID0gT1INCiAgZmlsdGVyKC4sIE1vbnRoPT0iSmFuIiB8IE1vbnRoPT0iSnVuIikNCmBgYA0KDQpgYGB7cn0NCm1lYW50d29tb250aHMgPC0gdHdvbW9udGhzICU+JQ0KICBncm91cF9ieShNb250aCkgJT4lDQogIHN1bW1hcmlzZShtZWFuPW1lYW4oVGVtcCwgbmEucm09VFJVRSkpDQoNCm1lYW50d29tb250aHMNCmBgYA0KYGBge3J9DQpnZ3Bsb3QodHdvbW9udGhzLCBhZXMoeD1UZW1wLCBjb2xvcj1Nb250aCwgZmlsbD1Nb250aCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0ocG9zaXRpb249ImlkZW50aXR5IiwgYWxwaGE9MC41KSsNCiAgZ2VvbV92bGluZShkYXRhPW1lYW50d29tb250aHMsIA0KICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0PW1lYW4sIA0KICAgICAgICAgICAgICAgICBjb2xvcj1Nb250aCksDQogICAgICAgICAgICAgbGluZXR5cGU9ImRhc2hlZCIpKw0KICBsYWJzKHRpdGxlPSJHZ3Bsb3QyIGhpc3RvZ3JhbSBvZiBBdXN0cmFsaWFuIEphbiBhbmQgSnVuDQogICAgICAgdGVtcGVyYXR1cmVzIiwNCiAgICAgICB4PSJUZW1wZXJhdHVyZSIsDQogICAgICAgeT0iRnJlcXVlbmN5IikrDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCmBgYHtyfQ0KZGF0YV9jb21wbGV0ZV9jYXNlcyA8LSBzcXVpc2hkYXRhICU+JQ0KICBkcm9wX25hKCklPiUgI2Ryb3BwZWQgYWxsIHRoZSBOQXMNCiAgIyBNb250aCBjb2x1bW4gbWFwIGluIGRlc2NlbmRpbmcgb3JkZXIgKGUuZy4gSmFuLCBGZWIsIE1hcmNoLi4pDQogIG11dGF0ZShNb250aCA9IGZhY3RvcihNb250aCwgbGV2ZWxzID0gYygiSmFuIiwiRmViIiwiTWFyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBcHIiLCJNYXkiLCJKdW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkp1bCIsIkF1ZyIsIlNlcCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT2N0IiwiTm92IiwiRGVjIikpKQ0KDQojIFBsb3QgZmFjZXRlZCBoaXN0b2dyYW0NCmdncGxvdChkYXRhX2NvbXBsZXRlX2Nhc2VzLCBhZXMoeD1UZW1wLCBuYS5ybT1UUlVFKSkrDQogIGdlb21faGlzdG9ncmFtKGNvbG9yPSJibGFjayIsIGJpbndpZHRoID0gNSkrDQogIGxhYnModGl0bGU9IkdncGxvdDIgZmFjZXRlZCBoaXN0b2dyYW0gb2YgQXVzdHJhbGlhbiB0ZW1wZXJhdHVyZXMiLCANCiAgICAgICB4PSJUZW1wZXJhdHVyZSIsDQogICAgICAgeT0iRnJlcXVlbmN5IikrDQogIGZhY2V0X2dyaWQoTW9udGggfiAuKSsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCmBgYHtyfQ0KbGlicmFyeShwbG90bHkpDQojIHNwbGl0IHRoZSBkYXRhIGZvciBwbG90bHkgYmFzZWQgb24gbW9udGgNCg0KamFuIDwtIHNxdWlzaGRhdGEgJT4lDQogIGRyb3BfbmEoKSAlPiUNCiAgZmlsdGVyKC4sIE1vbnRoPT0iSmFuIikNCg0KanVuIDwtIHNxdWlzaGRhdGEgJT4lDQogIGRyb3BfbmEoKSAlPiUNCiAgZmlsdGVyKC4sIE1vbnRoPT0iSnVuIikNCg0KIyBnaXZlIGF4aXMgdGl0bGVzDQp4IDwtIGxpc3QgKHRpdGxlID0gIlRlbXBlcmF0dXJlIikNCnkgPC0gbGlzdCAodGl0bGUgPSAiRnJlcXVlbmN5IikNCg0KIyBzZXQgdGhlIGJpbiB3aWR0aA0KeGJpbnNubzwtbGlzdChzdGFydD0wLCBlbmQ9NDAsIHNpemUgPSAyLjUpDQoNCiMgcGxvdCB0aGUgaGlzdG9ncmFtIGNhbGxpbmcgYWxsIHRoZSB2YXJpYWJsZXMgd2UganVzdCBzZXQNCmloaXN0PC1wbG90X2x5KGFscGhhID0gMC42KSAlPiUNCiAgICAgICAgYWRkX2hpc3RvZ3JhbSh4ID0gamFuJFRlbXAsDQogICAgICAgIHhiaW5zPXhiaW5zbm8sIG5hbWU9IkphbnVhcnkiKSAlPiUNCiAgICAgICAgYWRkX2hpc3RvZ3JhbSh4ID0ganVuJFRlbXAsDQogICAgICAgIHhiaW5zPXhiaW5zbm8sIG5hbWU9Ikp1bmUiKSAlPiUgDQogICAgICAgIGxheW91dChiYXJtb2RlID0gIm92ZXJsYXkiLCB4YXhpcz14LCB5YXhpcz15KQ0KDQppaGlzdA0KYGBgDQoNCmBgYHtyfQ0KIyBtZWFuIHBlciBtb250aA0KbWVhbm9mYWxsIDwtIHNxdWlzaGRhdGEgJT4lDQogIGdyb3VwX2J5KE1vbnRoKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKFRlbXAsIG5hLnJtPVRSVUUpKQ0KDQojIHByaW50IHRoZSB0b3AgMQ0KaGVhZChtZWFub2ZhbGwsIG49MSkNCmBgYA0KDQpgYGB7cn0NCiMgc3RhbmRhcmQgZGV2aWF0aW9uIHBlciBtb250aA0Kc2RvZmFsbCA8LSBzcXVpc2hkYXRhICU+JQ0KICBncm91cF9ieShNb250aCkgJT4lDQogIHN1bW1hcml6ZShzZCA9IHNkKFRlbXAsIG5hLnJtPVRSVUUpKQ0KDQojIG1heGltdW0gcGVyIG1vbnRoDQptYXhvZmFsbCA8LSBzcXVpc2hkYXRhICU+JQ0KICBncm91cF9ieShNb250aCkgJT4lDQogIHN1bW1hcml6ZShtYXggPSBtYXgoVGVtcCwgbmEucm09VFJVRSkpDQoNCiMgbWluaW11bSBwZXIgbW9udGgNCm1pbm9mYWxsIDwtIHNxdWlzaGRhdGEgJT4lDQogIGdyb3VwX2J5KE1vbnRoKSAlPiUNCiAgc3VtbWFyaXplKG1pbiA9IG1pbihUZW1wLCBuYS5ybT1UUlVFKSkNCg0KIyBJbnRlcnF1YXJ0bGllIHJhbmdlIHBlciBtb250aA0KSVFSb2ZhbGwgPC0gc3F1aXNoZGF0YSAlPiUNCiAgZ3JvdXBfYnkoTW9udGgpICU+JQ0KICBzdW1tYXJpemUoSVFSID0gSVFSKFRlbXAsIG5hLnJtPVRSVUUpKQ0KDQojIHBlcmhhcHMgeW91IHdhbnQgdG8gc3RvcmUgbXVsdGlwbGUgb3V0cHV0cyBpbiBvbmUgbGlzdC4uDQpsb3Rzb2ZzdGF0cyA8LSBzcXVpc2hkYXRhICU+JQ0KICBncm91cF9ieShNb250aCkgJT4lDQogIHN1bW1hcml6ZShJUVIgPSBJUVIoVGVtcCwgbmEucm09VFJVRSksIA0KICAgICAgICAgICAgbWF4PW1heChUZW1wLCBuYS5ybT1UKSkNCg0KIyBvciB5b3Ugd2FudCB0byBrbm93IHRoZSBtZWFuIChvciBzb21lIG90aGVyIHN0YXQpIA0KI2ZvciB0aGUgd2hvbGUgeWVhciBhcyBvcHBvc2VkIHRvIGVhY2ggbW9udGguLi4NCg0KbWVhbndob2xleWVhcj1zcXVpc2hkYXRhICU+JQ0KICBzdW1tYXJpemUobWVhbnllYXIgPSBtZWFuKFRlbXAsIG5hLnJtPVRSVUUpKQ0KYGBgDQoNCg0KQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLg0KDQpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4NCg0KVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLg0K